#ifndef ABB_H
#define ABB_H
#include "Tuple.h"
#include "error.h"
#include "cw.h"
#include "cr.h"
typedef struct sAbb *Abb;

/* NOTA: la ausencia de precondición es equivalente a {PRE: TRUE} */

/* constructor
a = abb_empty (void)
{Pos: abb_length(a)=0 ^s (a->t)=Leaf }
*/
Abb
abb_empty (void);

/* agrega una clave y un dato 
{Pre: h=H ^ k=K ^d=D}
abb_add (h, k, d)
{Pos: k=K ^d=D ^(h=H (v) <E p :(h ->t).p =(k,d) : (h->t).(p<|0) < (h->t).p ^ (h->t).(p<|1) > (h->t).p>
*/
void
abb_add (Abb h, Key k, Data d);

/* devuelve si existe la clave en el abb
{Pre: h=H ^ k=K}
b = abb_exists (h, k)
{Pos: h=H ^ k=K ^ b = E! p ? pos(h->t)  :(h ->t).p =(k,d) }
*/
Bool
abb_exists (Abb h, Key k);

/* busca un dato segun la clave
   debe llamarse solo si abb_exists (l, k)
   si no lo encuentra devuelve NULL
{Pre: h=H!=NULL ^ k=K!=NULL  };
d = abb_search (h, k)
{Pos: h=H ^ k=K ^(d = NULL (v) E! p ? pos(h->t):(h ->t).p =(k,d))}
*/
Data
abb_search (Abb h, Key k);

/* borra la clave y el valor asociado
{Pre: h=H!=NULL ^ k=K!=NULL}
abb_del (h, k)
{Pos:k=K!=NULL ^ ( (¬abb_exist =>h=H) (v) (abb_exist => h=H-{(k,d)}) ) }
*/
void
abb_del (Abb h, Key k);

/* devuelve la cantidad de elementos
{Pre: h=H!=NULL }
n= abb_length (h)
{Pos: n=#h ^ h=H!=NULL}
*/
int
abb_length (Abb h);

/* Lee un abb desde un archivo*/
Abb
abb_fromFile(char *nomfile);

/* Graba un abb a un archivo*/
void
abb_toFile(char *nomfile, Abb h);


/* Destructor.
   Destruye todo el abb y su contenido
{Pre: h=H!=NULL }
abb_destroy (h)
{Pos: H!=NULL=h }
*/
Abb
abb_destroy(Abb h);

/* Imprime el árbol en orden */
void
abb_pprint (Abb h);

/*
  Es necesario implementar una función que se comporte como el invariante de representación de un AVL, pa` ve` que onda.
  No hay tiempo para transcribir pre y pos. Están en las notas del taller.
*/
Bool invariante(Abb h);

#endif
